package moonlit.chill.pay.service.impl.wechat;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse;
import lombok.extern.slf4j.Slf4j;
import moonlit.chill.pay.cache.PayConfigDataCache;
import moonlit.chill.pay.constants.Constants;
import moonlit.chill.pay.exception.PayException;
import moonlit.chill.pay.service.PayStrategy;
import moonlit.chill.pay.util.WxConfigUtil;
import moonlit.chill.pay.vo.PayConfig;
import moonlit.chill.pay.vo.PayResult;
import moonlit.chill.pay.vo.TradeParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * @author MoonlitChill
 * @date 2024/4/15 19:33
 */
@Slf4j
@Service("wxMiniPayStrategy")
public class WxMiniPayStrategyServiceImpl implements PayStrategy {

    @Resource
    private PayConfigDataCache payConfigDataCache;

    @Autowired
    private WxConfigUtil wxConfigUtil;

    private static final String TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ssXXX";

    @Override
    public PayResult<?> payMethod(TradeParam tradeParam) {
        log.info(String.format("微信小程序支付参数:%s", JSONUtil.toJsonStr(tradeParam)));
        try {
            if (StrUtil.isEmpty(tradeParam.getMiniOpenId())) {
                log.error("微信小程序支付获取miniOpenId为null");
                throw new PayException("请使用微信登录后再试");
            }
        } catch (Exception e) {
            log.error("微信小程序支付获取miniOpenId失败");
            throw new PayException("支付出现异常,请联系管理员");
        }
        PayResult<String> result = new PayResult<>();
        String outTradeNo = tradeParam.getTransNum();
        result.setTransNum(outTradeNo);
        try {
            PayConfig payConfig = payConfigDataCache.getPayConfig();
            Config config = wxConfigUtil.getConfig(payConfig);
            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
            PrepayRequest request = new PrepayRequest();
            request.setAppid(payConfig.getMiniAppId());
            request.setMchid(payConfig.getUId());
            request.setDescription(tradeParam.getPayTitle());
            request.setOutTradeNo(outTradeNo);
            request.setTimeExpire(DateUtil.format(tradeParam.getPayDeadLine(), TIME_FORMAT));
            request.setAttach(JSONUtil.toJsonStr(tradeParam.getAdditionalInfo()));
            Amount amount = new Amount();
            amount.setTotal(tradeParam.getTotalFee().multiply(new BigDecimal(100)).setScale(0, RoundingMode.HALF_UP).intValue());
            request.setAmount(amount);
            request.setNotifyUrl(payConfig.getNotifyUrl());
            Payer payer = new Payer();
            payer.setOpenid(tradeParam.getMiniOpenId());
            request.setPayer(payer);
            log.info(String.format("微信小程序发起支付参数:%s", JSONUtil.toJsonStr(request)));
            PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
            log.info(String.format("微信小程序发起支付返回:%s", JSONUtil.toJsonStr(response)));
            if (ObjectUtil.isNotEmpty(response)) {
                result.setSuccess(Boolean.TRUE);
                result.setResult(JSONUtil.toJsonStr(response));
            } else {
                result.error("发起支付失败，请联系管理员", Constants.PAY_FAIL_CODE);
            }
        } catch (Exception e) {
            result.errorWithException("发起支付失败，请联系管理员", Constants.PAY_ERROR_CODE, e);
        }
        return result;
    }
}
